//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1995-1999  Microsoft Corporation

Module Name:

rilhand.h

Abstract:


Notes:


--*/
/*
------------------------------------------------------------------------------
    Revision History
    Date                Author          Activity ID              Activity Headline
    2007-03-09     qinxuetao     CEDB200046239         Update ril driver to enable AT command test through extended ATCI
    2007-04-17     qinxuetao     WM600002434             Modified rilpm to send command when CmdThread is exit.
    2007-05-10     qinxuetao     WM600002914             Delay Dial commands to wait for radio to settle
    2007-08-14     qinxuetao     WM600009403             Only init STK after some delay since phone on
------------------------------------------------------------------------------
*/

#pragma once
#ifdef OEM2_DRIVER
#include "rilndisoem2.h"
#define DEFAULT_COM_MASK (EV_RXCHAR | EV_RLSD | EV_ERR | EV_BREAK | EV_EVENT2)
#else
#define DEFAULT_COM_MASK (EV_RXCHAR | EV_RLSD | EV_ERR | EV_BREAK)
#ifdef OEM1_DRIVER
#include "rilndisoem1.h"
#else
#include "rilndis.h"
#endif
#endif
//
//
//
#define NUM_TIMEOUT_INIT_ATTEMPTS   3
#define NUM_FAILURE_INIT_ATTEMPTS   20


// Default API execution time (in msec)
#define EXECTIME_API_DEFAULT        25

// Default API timeout (in msec)
#define TIMEOUT_API_DEFAULT         10000
#define TIMEOUT_CMD_NOOP            10000
#define TIMEOUT_CMD_INIT            20000
#define TIMEOUT_WAITFORINIT         20000

#define TIMEOUT_CMD_ONLINE          10000
#define TIMEOUT_DTRDROP             5000

#define MAX_DTR_ATTEMPTS            1
#define MAX_ATO_ATTEMPTS            3

#define COM_INIT_INDEX 0

#if defined(OEM1_DRIVER) || defined(OEM2_DRIVER) || defined(WAVECOM_DRIVER) || defined(EMP_DRIVER)
#define COM_REINIT_INDEX 1
#else
#define COM_REINIT_INDEX 0
#endif

#if defined(OEM1_DRIVER) || defined(WAVECOM_DRIVER)
#define COM_SMSINIT_INDEX 2
#endif

#if defined(WAVECOM_DRIVER)
#define SENDREGINIT(i) (i==COM_REINIT_INDEX)
#else
#define SENDREGINIT(i) (i==COM_INIT_INDEX)
#endif

#define ATCMD_LOG_RESPONSE         true
#define ATCMD_LOG_COMMAND          false
#define ATCMD_LOG_SUPPRESSED_TEXT  "<Suppressed>"
// Forward declarations
class CRilInstanceHandle;
class CComHandle;

#ifndef RIL_RADIO_RESILIENCE
class CMonitor;
#endif // ! RIL_RADIO_RESILIENCE

// API IDs
// WARNING: If you add or remove entries from this table,
// you MUST synchronize the change with the table in the registry
// which holds perf/timeout information about each API.
// Held in HKEY_LOCAL_MACHINE\Software\Microsoft\RIL\APIInfo\<ApiEnumId>

enum APIID {
    APIID_NONE                          = -1,
    APIID_GETSUBSCRIBERNUMBERS          = 0,
    APIID_GETOPERATORLIST,              // 1
    APIID_GETPREFERREDOPERATORLIST,     // 2
    APIID_ADDPREFERREDOPERATOR,         // 3
    APIID_REMOVEPREFERREDOPERATOR,      // 4
    APIID_GETCURRENTOPERATOR,           // 5
    APIID_REGISTERONNETWORK,            // 6
    APIID_UNREGISTERFROMNETWORK,        // 7
    APIID_GETREGISTRATIONSTATUS,        // 8
    APIID_GETCALLERIDSETTINGS,          // 9
    APIID_SETCALLERIDSTATUS,            // 10
    APIID_GETHIDEIDSETTINGS,            // 11
    APIID_SETHIDEIDSTATUS,              // 12
    APIID_GETDIALEDIDSETTINGS,          // 13
    APIID_SETDIALEDIDSTATUS,            // 14
    APIID_GETCLOSEDGROUPSETTINGS,       // 15
    APIID_SETCLOSEDGROUPSETTINGS,       // 16
    APIID_GETCALLFORWARDINGSETTINGS,    // 17
    APIID_ADDCALLFORWARDING,            // 18
    APIID_REMOVECALLFORWARDING,         // 19
    APIID_SETCALLFORWARDINGSTATUS,      // 20
    APIID_GETCALLWAITINGSETTINGS,       // 21
    APIID_SETCALLWAITINGSTATUS,         // 22
    APIID_SENDSUPSERVICEDATA,           // 23
    APIID_CANCELSUPSERVICEDATASESSION,  // 24
    APIID_DIAL,                         // 25
    APIID_ANSWER,                       // 26
    APIID_HANGUP,                       // 27
    APIID_SENDDTMF,                     // 28
    APIID_SETDTMFMONITORING,            // 29
    APIID_GETCALLLIST,                  // 30
    APIID_MANAGECALLS,                  // 31
    APIID_TRANSFERCALL,                 // 32
    APIID_GETLINESTATUS,                // 33
    APIID_GETAUDIOGAIN,                 // 34
    APIID_SETAUDIOGAIN,                 // 35
    APIID_GETAUDIODEVICES,              // 36
    APIID_SETAUDIODEVICES,              // 37
    APIID_GETAUDIOMUTING,               // 38
    APIID_SETAUDIOMUTING,               // 39
    APIID_GETHSCSDOPTIONS,              // 40
    APIID_SETHSCSDOPTIONS,              // 41
    APIID_GETHSCSDCALLSETTINGS,         // 42
    APIID_GETDATACOMPRESSION,           // 43
    APIID_SETDATACOMPRESSION,           // 44
    APIID_GETERRORCORRECTION,           // 45
    APIID_SETERRORCORRECTION,           // 46
    APIID_GETBEARERSERVICEOPTIONS,      // 47
    APIID_SETBEARERSERVICEOPTIONS,      // 48
    APIID_GETRLPOPTIONS,                // 49
    APIID_SETRLPOPTIONS,                // 50
    APIID_GETMSGSERVICEOPTIONS,         // 51
    APIID_SETMSGSERVICEOPTIONS,         // 52
    APIID_GETMSGCONFIG,                 // 53
    APIID_SETMSGCONFIG,                 // 54
    APIID_RESTOREMSGCONFIG,             // 55
    APIID_SAVEMSGCONFIG,                // 56
    APIID_READMSG,                      // 57
    APIID_DELETEMSG,                    // 58
    APIID_WRITEMSG,                     // 59
    APIID_SENDMSG,                      // 60
    APIID_SENDSTOREDMSG,                // 61
    APIID_SENDMSGACKNOWLEDGEMENT,       // 62
    APIID_GETUSERIDENTITY,              // 63
    APIID_GETPHONELOCKEDSTATE,          // 64
    APIID_UNLOCKPHONE,                  // 65
    APIID_GETLOCKINGSTATUS,             // 66
    APIID_SETLOCKINGSTATUS,             // 67
    APIID_CHANGELOCKINGPASSWORD,        // 68
    APIID_GETCALLBARRINGSTATUS,         // 69
    APIID_SETCALLBARRINGSTATUS,         // 70
    APIID_CHANGECALLBARRINGPASSWORD,    // 71
    APIID_GETEQUIPMENTINFO,             // 72
    APIID_GETEQUIPMENTSTATE,            // 73
    APIID_SETEQUIPMENTSTATE,            // 74
    APIID_GETPHONEBOOKOPTIONS,          // 75
    APIID_SETPHONEBOOKOPTIONS,          // 76
    APIID_READPHONEBOOKENTRIES,         // 77
    APIID_WRITEPHONEBOOKENTRY,          // 78
    APIID_DELETEPHONEBOOKENTRY,         // 79
    APIID_SENDSIMCMD,                   // 80
    APIID_SENDRESTRICTEDSIMCMD,         // 81
    APIID_GETSIMRECORDSTATUS,           // 82
    APIID_GETSIMTOOLKITPROFILE,         // 83
    APIID_SETSIMTOOLKITPROFILE,         // 84
    APIID_SENDSIMTOOLKITENVELOPECMD,    // 85
    APIID_FETCHSIMTOOLKITCMD,           // 86
    APIID_SENDSIMTOOLKITCMDRESPONSE,    // 87
    APIID_TERMINATESIMTOOLKITSESSION,   // 88
    APIID_GETCOSTINFO,                  // 89
    APIID_SETCOSTINFO,                  // 90
    APIID_GETSIGNALQUALITY,             // 91
    APIID_GETCELLTOWERINFO,             // 92
    APIID_DEVSPECIFIC,                  // 93
    APIID_GETDEVCAPS,                   // 94
    APIID_GETHIDECONNECTEDIDSETTINGS,   // 95
    APIID_SETHIDECONNECTEDIDSTATUS,     // 96
    APIID_GETUUSREQUIREDSTATUS,         // 97
    APIID_CLEARCCBSREGISTRATION,        // 98
    APIID_GETSYSTEMTIME,                    // 99
    APIID_GETGPRSCONTEXTLIST,               // 100
    APIID_SETGPRSCONTEXT,                   // 101
    APIID_DELETEGPRSCONTEXT,                // 102
    APIID_GETREQUESTEDQUALITYOFSERVICELIST, // 103
    APIID_SETREQUESTEDQUALITYOFSERVICE,     // 104
    APIID_DELETEREQUESTEDQUALITYOFSERVICE,  // 105
    APIID_GETMINIMUMQUALITYOFSERVICELIST,   // 106
    APIID_SETMINIMUMQUALITYOFSERVICE,       // 107
    APIID_DELETEMINIMUMQUALITYOFSERVICE,    // 108
    APIID_SETGPRSATTACHED,                  // 109
    APIID_GETGPRSATTACHED,                  // 110
    APIID_SETGPRSCONTEXTACTIVATED,          // 111
    APIID_GETGPRSCONTEXTACTIVATEDLIST,      // 112
    APIID_ENTERGPRSDATAMODE,                // 113
    APIID_GETGPRSADDRESS,                   // 114
    APIID_GPRSANSWER,                       // 115
    APIID_GETGPRSREGISTRATIONSTATUS,        // 116
    APIID_GETGPRSCLASS,                     // 117
    APIID_SETGPRSCLASS,                     // 118
    APIID_GETMOSMSSERVICE,                  // 119
    APIID_SETMOSMSSERVICE,                  // 120
    APIID_GETCBMSGCONFIG,                   // 121
    APIID_SETCBMSGCONFIG,                   // 122
    APIID_GETCURRENTADDRESSID,              // 123
    APIID_SETCURRENTADDRESSID,              // 124
    APIID_GETPACKETBYTECOUNT,               // 125
    APIID_RESETPACKETBYTECOUNT,             // 126
    APIID_GETCURRENTPRIVACYSTATUS,          // 127
    APIID_GETCURRENTSYSTEMTYPE,             // 128
    APIID_GETALLOPERATORSLIST,              // 129
    APIID_REBOOTRADIO,                      // 130
    APIID_REGISTERATCOMMANDLOGGING,         // 131
    APIID_ATCOMMANDLOGFILE,                 // 132
    APIID_GETATR,                           // 133
    APIID_SENDSIMTOOLKITEVENTDOWNLOAD,      // 134
    APIID_LOGEVENTTORADIO,                  // 135
    APIID_GETVTSERIALPORTHANDLE,            // 136
    APIID_TOTAL                             // 137
};


// API information structure
struct APIINFO {
    DWORD dwExecTime;
    DWORD dwTimeout;
};


// Structure used for specifying init strings
struct INITSTRING_DATA {
    LPCSTR szCmd;
    DWORD dwCmdOption;
};


//
//
//
class CRilHandle
{
public:
            CRilHandle();
            ~CRilHandle();

    BOOL            StartInit();
    void            FinishInit(CCommand* pInitCmd, BOOL bSucceeded);
    void            GeneralInitDone(BOOL bSucceeded);

    void            PrepareForReinit();
    BOOL            LaunchThreads();
    BOOL            FCancelSet() const;
    BOOL            WaitForInit(DWORD dwTimeout) const;
    BOOL            WaitForCommandOrCancel() const;
    BOOL            AddToList(CRilInstanceHandle* const pInstance);
    BOOL            RemoveFromList(CRilInstanceHandle* const pInstance);
    HRESULT         GetNextCmdID();
    void            SendReadyStateNotification(DWORD dwReadyState);
    void            BroadcastNotification(CNotificationData*& rpnd);
    BOOL            BroadcastRealBlobNotification(const DWORD dwNotificationCode, const void* const pBlob,
                                                  const UINT cbBlob);
    BOOL            BroadcastDWORDBlobNotification(const DWORD dwNotificationCode, const DWORD dwBlob);
    BOOL            BroadcastATLogBlobNotification(const void* const pBlob, UINT uBlob, BOOL fResponse);
    BOOL            HandleRsp(CCommand*& rpCmd, CResponse*& rpRsp, BOOL& rfHungUp, BOOL& rfRadioOff);
    BOOL            AppendReadBytes(LPCSTR szBytes, UINT cbBytes, bool fUseBuffer2);
    BOOL            InheritReadBytes(CResponse* const pRsp, bool fUseBuffer2);
    BOOL            GiveUpReadBytes(LPSTR& rszBytes, UINT& rcbBytes, bool fUseBuffer2);
#ifndef RIL_RADIO_RESILIENCE
    BOOL            RegisterWithCPM();
#endif // ! RIL_RADIO_RESILIENCE
    void            GetAPIInfo(APIID apiid, APIINFO& rapii);
    CCheckPoint*    GetCheckPoint() const               { return m_pCheckPoint; };
    CComHandle*     GetComDevice() const                { return m_pComDevice; };
    DWORD           GetDataModeCmdDelay() const         { return m_dwDataModeCmdDelay; };
    DWORD           GetMaxDataModeTimeWithoutCmd() const { return m_dwMaxDataModeTimeWithoutCmd; };
    void            StartWaitingForRsp(CCommand *pCmd)
    {
        m_fWaitingForRsp = TRUE;
        m_pCurrCommand = pCmd;
    }
    void            SetLastCommandTimedOut() { if (m_pReadBytes && m_pReadBytes->GetLength() > 0) m_fLastCommandTimedOut = TRUE; }

    void            SetDataEvent()                      { SetEvent(m_hDataEvent); }
    void            StopWaitingForRsp()                 { m_fWaitingForRsp = FALSE; };
    BOOL            FWaitingForRsp() const              { return !!m_fWaitingForRsp; };
    BOOL            SetEmergencyMode(const BOOL fMode);
    BOOL            FInEmergencyMode()                  { SYNCBLOCK(m_csEmergency); return !!m_fEmergencyMode; };
    DWORD           ResponseThread();
    DWORD           CommandThread();
    DWORD           PmThread ();
    DWORD           SimReadyThread();
    void            StartReadyStateQuery();
    void            StopReadyStateQuery();
    BOOL            HandleRxData(char *szData, DWORD dwRead, bool fDataOnSecondComPort);
    void            SetAtLogOwner(CRilInstanceHandle* pRilInstanceHandle) { m_hATCommandLogOwner = pRilInstanceHandle; };
    void            LogATCommand(  LPCSTR szChars, UINT cbToWrite, BOOL fResponse);
    CRilNDIS        CRilNdis; 
private:
    
    HANDLE                          m_hInitEvent;
    HANDLE                          m_hCancelEvent;
    HANDLE                          m_hDataEvent;
    HANDLE                          m_hSimReadyEvent;
    HANDLE                          m_hInitedForSMSEvent;
    HANDLE                          m_hInitedForSIMPBEvent;
    HANDLE                          m_hCmdThread;
    HANDLE                          m_hReadThread;
    BOOL                            m_fQuitReadyStateThread;
    DWORD                           m_dwCmdThreadID;
    DWORD                           m_dwReadThreadID;
    CCheckPoint*                    m_pCheckPoint;
#ifndef RIL_RADIO_RESILIENCE
    CMonitor*                       m_pMonitor;
#endif // ! RIL_RADIO_RESILIENCE
    CDblList<CRilInstanceHandle>*   m_pInstances;
    HRESULT                         m_hrNextCmdID;
    CRITICAL_SECTION                m_cs;
    CRITICAL_SECTION                m_csInstances;
    CRITICAL_SECTION                m_csCmdID;
    CRITICAL_SECTION                m_csEmergency;
    CComHandle*                     m_pComDevice;
    CBuffer*                        m_pReadBytes;
#ifdef OEM2_DRIVER
    CBuffer*                        m_pReadBytes2;
#endif
    DWORD                           m_dwDataModeCmdDelay;
    DWORD                           m_dwMaxDataModeTimeWithoutCmd;
    APIINFO*                        m_rgpAPIInfo[APIID_TOTAL];
    DWORD                           m_fInited : 1;
    DWORD                           m_fFailedInit : 1;
    DWORD                           m_fInitedForSMS : 1;
    DWORD                           m_fInitedForSIMPB : 1;
    DWORD                           m_fWaitingForRsp : 1;
    DWORD                           m_fEmergencyMode : 1;
    DWORD                           m_fSimReady : 1;
    DWORD                           m_fLastCommandTimedOut : 1;
    DWORD                           m_dwSIMPBLastSize;
    CCommand*                       m_pCurrCommand;
    HANDLE                          m_hATCommandLogOwner;
};


typedef CUnboundedQueue<RILDRVNOTIFICATION> CRilNotificationQueue;

class CRilInstanceHandle : public CListElem
{
public:
                        CRilInstanceHandle();
                        ~CRilInstanceHandle();

    BOOL                Init(CRilHandle* const pDevice);
    void                Notify(const DWORD dwCode, const HRESULT hrCmdID, const void* const pBlob, const UINT cbBlob);
    BOOL                GetNextNotification(RILDRVNOTIFICATION& rrdnNotifyData);
    BOOL                CreateNotificationQueue(LPCTSTR tszEventName, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut);
    BOOL                FReadyForNotifications() const  { return !!m_fInited && m_notificationQ.Ready(); };
    CRilHandle*         GetDevice() const               { DEBUGCHK(FALSE != !!m_fInited); return m_pDevice; };
    CDblList<CCommand>* GetCmdList() const              { DEBUGCHK(FALSE != !!m_fInited); return m_pCmdList; };
    BOOL                MakePreferred();
    BOOL                FPreferred() const              { return !!m_fPreferred; };
    void                CancelNotifications() const     { if (m_hNotifyCancelEvent) {SetEvent(m_hNotifyCancelEvent);} }
    CRilInstanceNDIS    CRilInstanceNdis;
    CRilHandle*         GetCrilHandle (void)            { return m_pDevice; }

private:
    CRilHandle*                     m_pDevice;
    CDblList<CCommand>*             m_pCmdList;
    HANDLE                          m_hNotifyCancelEvent;
    CRilNotificationQueue           m_notificationQ;
    DWORD                           m_fInited : 1;
    DWORD                           m_fPreferred : 1;
};


// Functions
BOOL SendComInitString(UINT iString);
BOOL DeinitComPort(const CComHandle* const pComDevice);


// Externs
extern const LPCTSTR g_tszRegKeyRIL;
extern const LPCTSTR g_tszRegKeyAPIInfo;
extern const LPCTSTR g_tszRegKeyOperNames;
extern const LPCTSTR g_tszRegKeyRemoteCalltype;

extern DWORD g_TimeoutCmdInit;
extern DWORD g_TimeoutCmdNoOp;
extern DWORD g_TimeoutCmdOnline;
extern DWORD g_TimeoutAPIDefault;
extern DWORD g_TimeoutDTRDrop;
extern DWORD g_TimeoutWaitForInit;

BOOL NotifyHandle(void* pItem, DWORD dwData);

#ifdef WAVECOM_DRIVER
extern BOOL g_fNoSIM;
extern BOOL g_fEnableSTK;
#endif